/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ajustecurvas.controller;

import ajustecurvas.Ponto;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Luan
 */
public class PotenciaAjusteController extends AjusteController{
    
    List<Ponto> resultado;
    double pearson; // coeficiente de correlação de Pearson
    String equacao;

    @Override
    public List<Ponto> calcular(List<Ponto> medidas) {
        
        double[] x = separarEixo(medidas, 0);
        double[] y = separarEixo(medidas, 1);
        double[] logX = calcularLog(x);
        double[] logY = calcularLog(y);
        double[] produtoLogaritmos = calcularProdutoLogaritmos(logX, logY);
        double[] logXQuadrado = quadrado(logX);
        double[] logYQuadrado = quadrado(logY);
        int N = medidas.size();
        double A = calcularA(N, produtoLogaritmos, logX, logY, logXQuadrado);
        double B = calcularB(logY, A, logX, N);
        double rQuadrado = calcularRQuadrado(produtoLogaritmos, logX, logY, N, logXQuadrado, logYQuadrado);
        double p = A;
        double a = Math.exp(B);
       
        resultado = resultadoFuncao(a, x, p);
        pearson = rQuadrado;
        gerarEquacao(a, x, p);
        
        
        return resultado;
    }

    @Override
    public String getEquacao() {
        return equacao;
    }

    @Override
    public double getQualidade() {
        return pearson;
    }
    
    private double[] calcularProdutoLogaritmos(double[] X, double[] Y){
        double[] produto = new double[X.length];
        
        for(int i = 0; i< produto.length; i++)
            produto[i] = X[i] * Y[i];
        
        return produto;
    }

    private double[] calcularLog(double[] x) {
        
        double[] logaritmos = new double[x.length];
        
        for(int i = 0; i<logaritmos.length; i++)
            logaritmos[i] = Math.log(x[i]);
        
        return logaritmos;
    }
    
    private void calcularMinimosQuadrados(){
        
    }

    private double[] quadrado(double[] logaritmos) {
        double[] quadrado = new double[logaritmos.length];

        for(int j = 0; j<quadrado.length; j++){
            quadrado[j] = Math.pow(logaritmos[j], 2);
            
        }
        
        return quadrado;
    }

    private double calcularA(int N, double[] produtoLogaritmos, double[] logX, double[] logY, double[] logXQuadrado) {
        double A = ((N * soma(produtoLogaritmos))-(soma(logX) * soma(logY)))/((N * soma(logXQuadrado))-(Math.pow(soma(logX),2)));
        
        return A;
    }
    
    private double soma(double[] x){
        double soma = 0;
        
        for(int i = 0; i< x.length; i++)
            soma += x[i];
        
        return soma;
    }

    private double calcularB(double[] logY, double A, double[] logX, int N) {
        double B = (soma(logY)- (A * soma(logX)))/N;
        return B;
    }

    private double calcularRQuadrado(double[] produtoLogaritmos, double[] logX, double[] logY, int N, double[] logXQuadrado, double[] logYQuadrado) {
        double numerador ;
        double denominador;
        
        numerador = Math.pow((soma(produtoLogaritmos) - (((soma(logX) * soma(logY)))/N)), 2);
        denominador = (soma(logXQuadrado) - ((Math.pow(soma(logX),2)/N ))) * (soma(logYQuadrado) - ((Math.pow(soma(logY),2))/N));
       
        return numerador/denominador;
    }

    private double[] separarEixo(List<Ponto> medidas, int j) {
        double[] valores = new double[medidas.size()];
        
        for(int i = 0; i<valores.length; i++){
            if(j == 0)
                valores[i] = medidas.get(i).getX();
            else
                valores[i] = medidas.get(i).getY();
        }
        
        return valores;
    }

    private List<Ponto> resultadoFuncao(double a, double[] x, double p) {
        ArrayList<Ponto> result = new ArrayList<Ponto>();
        double y;
        
        for(int i = 0; i<x.length; i++){
            y = a * Math.pow(x[i], p);
            Ponto ponto = new Ponto(x[i], y);
            result.add(ponto);
        }
        
        return result;
    }

    private void gerarEquacao(double a, double[] x, double p) {
        DecimalFormat df = new DecimalFormat("0.00");  
        String A = df.format(a);
        String B = df.format(p);
        equacao = "" + A + " * (x ^ " + B + ")";
    }
    
}
